﻿using System;
using System.Data;
using System.Windows.Forms;
using DataSync.Models.Department;
using DataSync.Models.Staff;
using DataSync.Properties;
using DataSync.Services.Attendance;
using DataSync.Services.Common;
using DataSync.Services.Department;
using DataSync.Services.Staff;
using DataSync.Utilities;

namespace DataSync.Guis.Forms
{
    public partial class FrmMain : Form
    {
        public string _StartUpPath;
        private SystemTray _SystemTray;
        
        //Service
        private AttendanceService _AttendanceService;
        private DepartmentService _DepartmentService;
        private StaffService _StaffService;

        //Model
        private DataSet _DepartmentList;
        private DataSet _StaffList;

        //Misc
        private int _NumberCounter;
        private bool _SettingFound;
        private bool _LogFound;

        private int _AttendanceSyncTime;
        private DateTime _AttendanceSyncDate;
        private int _AttendanceSyncFrequency;
        
        private int _SendMailTime;
        private string _SendMailFrequency;
        private DateTime _SendMailDate;

        private int _EmployeeSyncTime;
        private DateTime _EmployeeSyncDate;
        
        public FrmMain()
        {
            InitializeComponent();
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            try
            {
                //Global parameter
                _StartUpPath = Application.StartupPath;

                Int32.TryParse(Resources.ParamNumberCounter, out _NumberCounter);

                //System tray
                var objValues = new object[2];
                objValues[0] = Resources.PodCast;
                _SystemTray = new SystemTray("° Attendance synchronization\n° Standby", null, true);
                _SystemTray.SetIconRange(objValues);
                _SystemTray.SetContextMenuOrStrip(cmsTrayIcon);                
            }
            catch(Exception exception)
            {
                MessageBox.Show(
                    Resources.MsgUnknowError + "\n" + Resources.MsgAdditionalInformation + exception.Message + " - " +
                    exception.InnerException,
                    Resources.CapUnknownError,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void tsmExit_Click(object sender, EventArgs e)
        {
            var dialogResult = MessageBox.Show(
                Resources.MsgConfirmExit,
                Resources.CapConfirm,
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question);

            if (dialogResult != DialogResult.Yes) 
                return;

            CommonService.SaveLog(Resources.OperationExitApplication, string.Empty);
            Close();
        }

        private void tmrFadding_Tick(object sender, EventArgs e)
        {
            try
            {
                if (pgbEnvironment.Value != 100)
                {
                    pgbEnvironment.Value += 20;
                    if (!_SettingFound)
                    {
                        _SettingFound = CommonService.RetrieveSetting(
                            _StartUpPath,
                            ref _AttendanceSyncTime,
                            ref _AttendanceSyncFrequency,
                            ref _SendMailTime,
                            ref _SendMailFrequency,
                            ref _EmployeeSyncTime);

                        if(!_SettingFound)
                        {
                            MessageBox.Show(
                                Resources.MsgSettingFileMissing,
                                Resources.CapError,
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                            Application.Exit();
                        }
                        else
                        {
                            if(!InitializeSetting())
                            {
                                MessageBox.Show(
                                    Resources.MsgInvalidSettingFile,
                                    Resources.CapError,
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);
                                Application.Exit();
                            }
                        }
                    }
                    else if (!_LogFound)
                    {
                        _LogFound = CommonService.DetectLogFile();

                        if(!_LogFound)
                        {
                            MessageBox.Show(
                                Resources.MsgLogMissing,
                                Resources.CapError,
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                            Application.Exit();
                        }
                    }
                }
                else if (pgbServer.Value != 100)
                    pgbServer.Value += 20;
                else if (pgbService.Value != 100)
                    pgbService.Value += 20;
                else if (Opacity != 0)
                    Opacity -= 0.1;
                else
                {
                    Visible = false;
                    tmrFadding.Enabled = false;
                    tsmSynchronizeFrequency.SelectedIndexChanged += tsmSynchronizeFrequency_SelectedIndexChanged;
                    tsmSynchronizeTime.SelectedIndexChanged += tsmSynchronizeTime_SelectedIndexChanged;
                    tsmSendMailFrequency.SelectedIndexChanged += tsmSendMailFrequency_SelectedIndexChanged;
                    tsmSendMailTime.SelectedIndexChanged += tsmSendMailTime_SelectedIndexChanged;
                    tsmSynchronizeStaffTime.SelectedIndexChanged += tsmSynchronizeStaffTime_SelectedIndexChanged;

                    CommonService.SaveLog(Resources.OperationLoadApplication, Resources.MsgLoadApplicationSuccess);
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show(
                    Resources.MsgUnknowError + "\n" + Resources.MsgAdditionalInformation + exception.Message + " - " +
                    exception.InnerException,
                    Resources.CapUnknownError,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);

                CommonService.SaveLog(Resources.OperationLoadApplication, exception.Message);
            }
        }

        private void tsmForceAllServers_Click(object sender, EventArgs e)
        {
            SynchronizeAttendance(0);
        }

        private void tsmForceFp_Click(object sender, EventArgs e)
        {
            SynchronizeAttendance(1);
        }

        private void tsmForceSocial_Click(object sender, EventArgs e)
        {
            SynchronizeAttendance(2);
        }

        private void tsmForceHotel_Click(object sender, EventArgs e)
        {
            SynchronizeAttendance(3);
        }

        private void tsmForceMamie_Click(object sender, EventArgs e)
        {
            SynchronizeAttendance(4);
        }

        private void tsmForceMechanisme_Click(object sender, EventArgs e)
        {
            SynchronizeAttendance(5);
        }

        private void SynchronizeAttendance(int serverIdentification)
        {
            if (_AttendanceService == null)
                _AttendanceService = new AttendanceService();

            _SystemTray.BaloonTipText = Resources.MsgSynchronizeInProgress;
            _SystemTray.ShowBaloonTrayTip(6000);

            var synchronizeResult = false;
            try
            {
                switch (serverIdentification)
                {
                    case 1:
                        synchronizeResult = _AttendanceService.MoveAttendances(1);
                        break;
                    case 2:
                        synchronizeResult = _AttendanceService.MoveAttendances(2);
                        break;
                    case 3:
                        synchronizeResult = _AttendanceService.MoveAttendances(3);
                        break;
                    case 4:
                        synchronizeResult = _AttendanceService.MoveAttendances(4);
                        break;
                    case 5:
                        synchronizeResult = _AttendanceService.MoveAttendances(5);
                        break;
                    default:
                        for (var counter = 1; counter <= _NumberCounter; counter++)
                        {
                            synchronizeResult = _AttendanceService.MoveAttendances(counter);
                            if(!synchronizeResult)
                                break;
                        }
                        break;
                }                
            }
            catch (Exception exception)
            {
                MessageBox.Show(
                    Resources.MsgUnknowError + "\n" + Resources.MsgAdditionalInformation + exception.Message + " - " +
                    exception.InnerException,
                    Resources.CapUnknownError,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                CommonService.SaveLog(Resources.OperationSynchronizeAttendance, exception.Message);
                return;
            }

            if (synchronizeResult)
            {
                _SystemTray.BaloonTipText = Resources.MsgSynchronizeSuccess;
                CommonService.SaveLog(Resources.OperationSynchronizeAttendance, Resources.MsgSynchronizeSuccess);
            }
            else
            {
                _SystemTray.BaloonTipText = Resources.MsgSynchronizeError;
                CommonService.SaveLog(Resources.OperationSynchronizeAttendance, Resources.MsgSynchronizeError);
            }
            _SystemTray.ShowBaloonTrayTip(6000);
        }

        private void tmrActionListener_Tick(object sender, EventArgs e)
        {
            try
            {                
                //Synchronize attendance
                if ((DateTime.Now.Hour.CompareTo(_AttendanceSyncDate.Hour) == 0) &&
                    (DateTime.Now.Day == _AttendanceSyncDate.Day))
                {
                    _AttendanceSyncDate = DateTime.Now.AddHours(_AttendanceSyncFrequency);
                    SynchronizeAttendance(0);                    
                }

                //Send mail
                if((DateTime.Now.Hour.CompareTo(_SendMailDate.Hour) == 0) &&
                    (_SendMailFrequency.Equals(Resources.SettingSendMailFrequencyDaily) || 
                    _SendMailFrequency.Equals(DateTime.Now.DayOfWeek.ToString())) &&
                    (DateTime.Now.Day == _SendMailDate.Day))
                {
                    _SendMailDate = _SendMailFrequency.Equals(Resources.SettingSendMailFrequencyDaily) ? _SendMailDate.AddDays(1) : _SendMailDate.AddDays(7);

                    if(GenerateReport())
                        SendReport();
                }

                //Synchronize employee
                if ((DateTime.Now.Hour.CompareTo(_EmployeeSyncDate.Hour) == 0) &&
                    (DateTime.Now.DayOfWeek.CompareTo(_EmployeeSyncDate.DayOfWeek) == 0))
                {
                    _EmployeeSyncDate = _EmployeeSyncDate.AddDays(1);
                    SynchronizeStaff();
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show(
                    Resources.MsgUnknowError + "\n" + Resources.MsgAdditionalInformation + exception.Message + " - " +
                    exception.InnerException,
                    Resources.CapUnknownError,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                CommonService.SaveLog(Resources.OperationListener, exception.Message);
            }
        }

        private void tsmForceSendMail_Click(object sender, EventArgs e)
        {
            SendReport();
        }

        private void SendReport()
        {
            bool actionResult;
            try
            {
                //Retrieve mail
                RetrieveContactMail();

                if (_AttendanceService == null)
                    _AttendanceService = new AttendanceService();

               _SystemTray.BaloonTipText = Resources.MsgSendMailInProgress;
                _SystemTray.ShowBaloonTrayTip(6000);
                
                actionResult = _AttendanceService.SendMail(_DepartmentList.Tables[0]);
            }
            catch (Exception exception)
            {
                MessageBox.Show(
                    Resources.MsgUnknowError + "\n" + Resources.MsgAdditionalInformation + exception.Message + " - " +
                    exception.InnerException,
                    Resources.CapUnknownError,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                CommonService.SaveLog(Resources.OperationSendReport, exception.Message);
                return;
            }

            if (actionResult)
            {
                _SystemTray.BaloonTipText = Resources.MsgSendMailSuccess;
                CommonService.SaveLog(Resources.OperationSendReport, Resources.MsgSendMailSuccess);
            }
            else
            {
                _SystemTray.BaloonTipText = Resources.MsgSendMailError;
                CommonService.SaveLog(Resources.OperationSendReport, Resources.MsgSendMailError);
            }
            
            _SystemTray.ShowBaloonTrayTip(6000);
        }        

        private bool InitializeSetting()
        {
            //Synchronize time
            var selectedIndex = tsmSynchronizeTime.FindString(StringHelper.Right("00" + _AttendanceSyncTime, 2), -1);
            if(selectedIndex == -1)
                return false;
            tsmSynchronizeTime.SelectedIndex = selectedIndex;

            //Synchronize frequency
            selectedIndex = tsmSynchronizeFrequency.FindString(Resources.ParamSynchronizeFrequencyPrefix + _AttendanceSyncFrequency, -1);
            if (selectedIndex == -1)
                return false;
            tsmSynchronizeFrequency.SelectedIndex = selectedIndex;

            //Send mail time            
            selectedIndex = tsmSendMailTime.FindString(StringHelper.Right("00" + _SendMailTime, 2), -1);
            if (selectedIndex == -1)
                return false;
            tsmSendMailTime.SelectedIndex = selectedIndex;

            //Send mail frequency
            selectedIndex = tsmSendMailFrequency.FindString(_SendMailFrequency);
            if (selectedIndex == -1)
                return false;
            tsmSendMailFrequency.SelectedIndex = selectedIndex;

            //Time to synchronize employee
            selectedIndex = tsmSynchronizeTime.FindString(StringHelper.Right("00" + _EmployeeSyncTime, 2), -1);
            if (selectedIndex == -1)
                return false;
            tsmSynchronizeStaffTime.SelectedIndex = selectedIndex;

            _AttendanceSyncDate = DateTime.Parse(DateTime.Today.ToShortDateString() + " " + StringHelper.Right("00" + _AttendanceSyncTime, 2) + ":00");
            _SendMailDate = DateTime.Parse(DateTime.Today.ToShortDateString() + " " + StringHelper.Right("00" + _SendMailTime, 2) + ":00");
            _EmployeeSyncDate = DateTime.Parse(DateTime.Today.ToShortDateString() + " " + StringHelper.Right("00" + _EmployeeSyncTime, 2) + ":00");
            return true;
        }

        private void tsmSynchronizeFrequency_SelectedIndexChanged(object sender, EventArgs e)
        {
            var synchronizeFrequency = tsmSynchronizeFrequency.Text;
            if (string.IsNullOrEmpty(synchronizeFrequency))
                return;

            synchronizeFrequency = synchronizeFrequency.Replace(Resources.ParamSynchronizeFrequencySuffixs, string.Empty);
            synchronizeFrequency = synchronizeFrequency.Replace(Resources.ParamSynchronizeFrequencySuffix, string.Empty);
            synchronizeFrequency = synchronizeFrequency.Replace(Resources.ParamSynchronizeFrequencyPrefix, string.Empty);

            Int32.TryParse(synchronizeFrequency, out _AttendanceSyncFrequency);
            CommonService.SaveSetting(
                _StartUpPath,
                _AttendanceSyncTime,
                _AttendanceSyncFrequency,
                ref _AttendanceSyncDate,
                _SendMailTime,
                ref _SendMailDate,
                _SendMailFrequency,
                _EmployeeSyncTime,
                ref _EmployeeSyncDate);
        }

        private void tsmSynchronizeTime_SelectedIndexChanged(object sender, EventArgs e)
        {
            var synchronizeTime = tsmSynchronizeTime.Text;
            if (string.IsNullOrEmpty(synchronizeTime))
                return;

            synchronizeTime = synchronizeTime.Replace(Resources.ParamTimeSuffix, string.Empty);

            Int32.TryParse(synchronizeTime, out _AttendanceSyncTime);
            CommonService.SaveSetting(
                _StartUpPath,
                _AttendanceSyncTime,
                _AttendanceSyncFrequency,
                ref _AttendanceSyncDate,
                _SendMailTime,
                ref _SendMailDate,
                _SendMailFrequency,
                _EmployeeSyncTime,
                ref _EmployeeSyncDate);
        }

        private void tsmSendMailFrequency_SelectedIndexChanged(object sender, EventArgs e)
        {
            _SendMailFrequency = tsmSendMailFrequency.Text;
            CommonService.SaveSetting(
                _StartUpPath,
                _AttendanceSyncTime,
                _AttendanceSyncFrequency,
                ref _AttendanceSyncDate,
                _SendMailTime,
                ref _SendMailDate,
                _SendMailFrequency,
                _EmployeeSyncTime,
                ref _EmployeeSyncDate);
        }

        private void tsmSendMailTime_SelectedIndexChanged(object sender, EventArgs e)
        {
            var sendMailTime = tsmSendMailTime.Text;
            if (string.IsNullOrEmpty(sendMailTime))
                return;

            sendMailTime = sendMailTime.Replace(Resources.ParamTimeSuffix, string.Empty);

            Int32.TryParse(sendMailTime, out _SendMailTime);
            CommonService.SaveSetting(
                _StartUpPath,
                _AttendanceSyncTime,
                _AttendanceSyncFrequency,
                ref _AttendanceSyncDate,
                _SendMailTime,
                ref _SendMailDate,
                _SendMailFrequency,
                _EmployeeSyncTime,
                ref _EmployeeSyncDate);
        }

        private void RetrieveContactMail()
        {            
            try
            {
                if (_DepartmentService == null)
                    _DepartmentService = new DepartmentService();

                _DepartmentList = Department.GenearteDepartment();
                _DepartmentList.Tables[0].Merge(_DepartmentService.GetDepartments());
                CommonService.SaveLog(Resources.OperationRetrieveMail, Resources.MsgRetrieveMailSuccess);
            }
            catch (Exception exception)
            {
                MessageBox.Show(
                    Resources.MsgUnknowError + "\n" + Resources.MsgAdditionalInformation + exception.Message + " - " +
                    exception.InnerException,
                    Resources.CapUnknownError,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                CommonService.SaveLog(Resources.OperationRetrieveMail, exception.Message);
            }
        }

        private void tsmSynchronizeStaffTime_SelectedIndexChanged(object sender, EventArgs e)
        {
            var syncEmployeeTime = tsmSynchronizeStaffTime.Text;
            if (string.IsNullOrEmpty(syncEmployeeTime))
                return;

            syncEmployeeTime = syncEmployeeTime.Replace(Resources.ParamTimeSuffix, string.Empty);

            Int32.TryParse(syncEmployeeTime, out _EmployeeSyncTime);
            CommonService.SaveSetting(
                _StartUpPath,
                _AttendanceSyncTime,
                _AttendanceSyncFrequency,
                ref _AttendanceSyncDate,
                _SendMailTime,
                ref _SendMailDate,
                _SendMailFrequency,
                _EmployeeSyncTime,
                ref _EmployeeSyncDate);
        }

        private void SynchronizeStaff()
        {
            try
            {
                if (_StaffService == null)
                    _StaffService = new StaffService();

                var syncResult = true;
                _StaffList = Staff.GenearteStaff();
                _StaffList.Tables[0].Merge(_StaffService.GetStaffs());

                _SystemTray.BaloonTipText = Resources.MsgSynchronizeInProgress;
                _SystemTray.ShowBaloonTrayTip(6000);

                for (var counter = 1; counter <= _NumberCounter; counter++)
                {
                    _StaffService.DeleteStaffs(counter);
                    CommonService.SaveLog(Resources.OperationSynchronizeStaff, Resources.MsgDeleteStaffSuccess + counter);
                    if (_StaffService.InsertStaff(_StaffList.Tables[0], counter))
                    {
                        CommonService.SaveLog(Resources.OperationSynchronizeStaff, Resources.MsgInsertStaffSuccess + counter);
                        continue;
                    }
                    syncResult = false;
                    break;
                }

                if (syncResult)
                {
                    CommonService.SaveLog(Resources.OperationSynchronizeStaff, Resources.MsgSynchronizeSuccess);
                    _SystemTray.BaloonTipText = Resources.MsgSynchronizeSuccess;
                }
                else
                {
                    CommonService.SaveLog(Resources.OperationSynchronizeStaff, Resources.MsgSynchronizeError);
                    _SystemTray.BaloonTipText = Resources.MsgSynchronizeError;                    
                }
                _SystemTray.ShowBaloonTrayTip(6000);
                return;
            }
            catch (Exception exception)
            {
                CommonService.SaveLog(Resources.OperationSynchronizeStaff, exception.Message);
                MessageBox.Show(                                    
                    Resources.MsgUnknowError + "\n" + Resources.MsgAdditionalInformation + exception.Message + " - " + exception.InnerException,
                    Resources.CapUnknownError,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void tsmForceSynchronizeStaff_Click(object sender, EventArgs e)
        {
            SynchronizeStaff();
        }

        private void tsmForceGenerateReport_Click(object sender, EventArgs e)
        {
            GenerateReport();
        }

        private bool GenerateReport()
        {
            var actionResult = false;
            try
            {
                //Generate reports
                _SystemTray.BaloonTipText = Resources.MsgGenerateReport;
                _SystemTray.ShowBaloonTrayTip(6000);

                if (_AttendanceService == null)
                    _AttendanceService = new AttendanceService();
                actionResult = _AttendanceService.GenerateReport(_DepartmentList.Tables[0]);

                _SystemTray.BaloonTipText = actionResult ? Resources.MsgGenerateReportSuccess : Resources.MsgGenerateReportError;
                _SystemTray.ShowBaloonTrayTip(6000);
            }
            catch (Exception exception)
            {
                CommonService.SaveLog(Resources.OperationSynchronizeStaff, exception.Message);
                MessageBox.Show(
                    Resources.MsgUnknowError + "\n" + Resources.MsgAdditionalInformation + exception.Message + " - " + exception.InnerException,
                    Resources.CapUnknownError,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }

            return actionResult;
        }
    }
}